package com.chaintor.demo.math;

import org.apache.commons.math3.util.FastMath;

/**
 * SABR的波动率的函数
 * 给定汇率，执行价，bate,期限,通过SABR的3个参数计算出波动率
 */
public class SigmaSABRFunction {
    private double m_beta;
    private double m_F;
    private double m_K;
    private double m_T;

    /**
     * 给定汇率，执行价，bate,期限 构建函数
     * @param f
     * @param k
     * @param b
     * @param exp_to_t
     */
    public SigmaSABRFunction(double f, double k, double b, double exp_to_t){
        m_F = f;
        m_K = k;
        m_beta = b;
        m_T = exp_to_t/365.0;
    }

    /**
     * 输入SABR的 alpha,rho,nu 计算波动率
     * @param alpha
     * @param rho
     * @param nu
     * @return
     */
    public double value(double alpha,double rho,double nu){
        double y = nu * FastMath.log(m_F/m_K)/fx(fz(nu,alpha),rho)*(1.0+((1.0-m_beta)*(1.0-m_beta)/24.0*(alpha*alpha/FastMath.pow(m_F*m_K,1.0-m_beta)+0.25*(rho*m_beta*nu*alpha/FastMath.pow(m_F*m_K,(1.0-m_beta)/2.0))+(2.0-3.0*rho*rho)/24.0*nu*nu))*m_T);
        return y;
    }

    private double fx(double z,double rho){
        return FastMath.log((FastMath.sqrt(1.0-2.0*rho*z+z*z)+z-rho)/(1-rho));
    }

    private double fz(double nu,double alpha){
        double z = 0.0;
        if (m_beta < 1.0){
            z = nu/alpha * ((FastMath.pow(m_F,1.0-m_beta)-FastMath.pow(m_K,1.0-m_beta))/(1.0-m_beta));
        }else{
            z = nu/alpha * FastMath.log(m_F/m_K);
        }
        return z;
    }
}
